use std::io;

use etherparse::Ipv4Header;

use crate::TIME_TO_LIVE;

/// ```
///                               +---------+ ---------\      active OPEN
///                               |  CLOSED |            \    -----------
///                               +---------+<---------\   \   create TCB
///                                 |     ^              \   \  snd SYN
///                    passive OPEN |     |   CLOSE        \   \
///                    ------------ |     | ----------       \   \
///                     create TCB  |     | delete TCB         \   \
///                                 V     |                      \   \
///                               +---------+            CLOSE    |    \
///                               |  LISTEN |          ---------- |     |
///                               +---------+          delete TCB |     |
///                    rcv SYN      |     |     SEND              |     |
///                   -----------   |     |    -------            |     V
///  +---------+      snd SYN,ACK  /       \   snd SYN          +---------+
///  |         |<-----------------           ------------------>|         |
///  |   SYN   |                    rcv SYN                     |   SYN   |
///  |   RCVD  |<-----------------------------------------------|   SENT  |
///  |         |                    snd ACK                     |         |
///  |         |------------------           -------------------|         |
///  +---------+   rcv ACK of SYN  \       /  rcv SYN,ACK       +---------+
///    |           --------------   |     |   -----------
///    |                  x         |     |     snd ACK
///    |                            V     V
///    |  CLOSE                   +---------+
///    | -------                  |  ESTAB  |
///    | snd FIN                  +---------+
///    |                   CLOSE    |     |    rcv FIN
///    V                  -------   |     |    -------
///  +---------+          snd FIN  /       \   snd ACK          +---------+
///  |  FIN    |<-----------------           ------------------>|  CLOSE  |
///  | WAIT-1  |------------------                              |   WAIT  |
///  +---------+          rcv FIN  \                            +---------+
///    | rcv ACK of FIN   -------   |                            CLOSE  |
///    | --------------   snd ACK   |                           ------- |
///    V        x                   V                           snd FIN V
///  +---------+                  +---------+                   +---------+
///  |FINWAIT-2|                  | CLOSING |                   | LAST-ACK|
///  +---------+                  +---------+                   +---------+
///    |                rcv ACK of FIN |                 rcv ACK of FIN |
///    |  rcv FIN       -------------- |    Timeout=2MSL -------------- |
///    |  -------              x       V    ------------        x       V
///     \ snd ACK                 +---------+delete TCB         +---------+
///      ------------------------>|TIME WAIT|------------------>| CLOSED  |
///                               +---------+                   +---------+
/// ```
///                       TCP Connection State Diagram
pub enum State {
    Closed,
    SynRcvd,
    Estab,
}

/// Transmission Control Block
/// 因为TCP是长连接，所以需要保存一些发送过程中的状态
pub struct TCB {
    state: State,
    send: SendSequence,
    recv: ReceiveSequence,
    ip: Ipv4Header,
}

/// Send Sequence Space
/// ```
///             1         2          3          4
///         ----------|----------|----------|----------
///                 SND.UNA    SND.NXT    SND.UNA
///                                      +SND.WND
///
/// 1 - old sequence numbers which have been acknowledged
/// 2 - sequence numbers of unacknowledged data
/// 3 - sequence numbers allowed for new data transmission
/// 4 - future sequence numbers which are not yet allowed
/// ```
///                     Send Sequence Space
struct SendSequence {
    /// send unacknowledged
    una: u32,
    /// send next
    nxt: u32,
    /// send window
    wnd: u16,
    /// send urgent pointer
    up: bool,
    wl1: usize,
    wl2: usize,
    iss: u32,
}

impl SendSequence {
    fn new(una: u32, nxt: u32, wnd: u16, up: bool, wl1: usize, wl2: usize, iss: u32) -> Self {
        Self {
            una,
            nxt,
            wnd,
            up,
            wl1,
            wl2,
            iss,
        }
    }
}

struct ReceiveSequence {
    nxt: u32,
    wnd: u16,
    up: bool,
    irs: u32,
}

impl ReceiveSequence {
    fn new(nxt: u32, wnd: u16, up: bool, irs: u32) -> Self {
        Self { nxt, wnd, up, irs }
    }
}

impl TCB {
    pub fn accept<'a>(
        iface: &mut tun_tap::Iface,
        ip_header: etherparse::Ipv4HeaderSlice<'a>,
        tcp_header: etherparse::TcpHeaderSlice<'a>,
        data: &'a [u8],
    ) -> io::Result<Option<Self>> {
        if !tcp_header.syn() {
            return Ok(None);
        }
        let mut buf = vec![0u8; 1500];
        let mut tcb = TCB {
            state: State::SynRcvd,
            send: SendSequence::new(
                0,
                1,
                10,
                false,
                0,
                0,
                0,
            ),
            recv: ReceiveSequence::new(
                tcp_header.sequence_number() + 1,
                tcp_header.window_size(),
                tcp_header.urg(),
                tcp_header.sequence_number(),
            ),
            ip: etherparse::Ipv4Header::new(
                0,
                TIME_TO_LIVE,
                etherparse::IpNumber::Tcp as u8,
                ip_header.destination(),
                ip_header.source(),
            ),
        };

        // 接受到的TCP的头部中的目的端口就是我们程序的端口，即下方要填的源端口，目的端口则是TCP头的源端口
        let mut syn_ack = etherparse::TcpHeader::new(
            tcp_header.destination_port(),
            tcp_header.source_port(),
            tcb.send.iss,
            tcb.send.wnd,
        );
        tcb.ip.payload_len = syn_ack.header_len();
        // SYN
        syn_ack.syn = true;
        // ACK
        syn_ack.ack = true;
        // ack
        syn_ack.acknowledgment_number = tcb.recv.nxt;
        let unwirtten = {
            let mut unwritten = &mut buf[..];
            tcb.ip.write(&mut unwritten).expect("ip write error");
            syn_ack.write(&mut unwritten)?;
            unwritten.len()
        };
        eprintln!("send {:02x?}", &buf[..unwirtten]);
        iface.send(&buf[..unwirtten])?;
        Ok(Some(tcb))
        // Ok(None)
    }

    pub fn receive_packet<'a> (
        &self,
        iface: &mut tun_tap::Iface,
        ip_header: etherparse::Ipv4HeaderSlice<'a>,
        tcp_header: etherparse::TcpHeaderSlice<'a>,
        data: &'a [u8],
    ) -> io::Result<()> {
        // 检查ack是否落于正确的区间
        if !ack_is_valid(self.send.una, tcp_header.acknowledgment_number(), self.send.nxt) {
            return Err(io::Error::new(io::ErrorKind::BrokenPipe, "error ack"));
        }
        // 检查seq是否落于正确区间,
        // Segment Receive  Test
        // Length  Window
        // ------- -------  -------------------------------------------   
        //    0       0     SEG.SEQ = RCV.NXT   
        //    0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND   
        //   >0       0     not acceptable   
        //   >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
        //               or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
        let seg_len = data.len() as u32;
        let wnd = self.recv.wnd as u32;
        let seq = tcp_header.sequence_number();
        // seg_len == 0的情况
        if seg_len == 0 {
            if (wnd == 0 && seq != self.recv.nxt) ||
                (wnd > 0 && !ack_is_valid(self.recv.nxt, seq, self.recv.nxt.wrapping_add(wnd))) {
                return Err(io::Error::new(io::ErrorKind::InvalidData, "seq is not equals to nxt or seq is not valid"));
            }
        }
        // 下面开始是seg_len > 0的情况
        if wnd == 0 {
            return Ok(());
        }
        if !seq_is_valid(self.recv.nxt, seq, self.recv.nxt.wrapping_add(wnd))
            && !seq_is_valid(self.recv.nxt, seq + data.len() as u32 - 1, self.recv.nxt.wrapping_add(wnd)) {
            return Ok(());
        }
        eprintln!(
            "{}: {} -> {}: {}, total {} b of tcp",
            ip_header.source_addr(),
            tcp_header.source_port(),
            ip_header.destination_addr(),
            tcp_header.destination_port(),
            data.len()
        );
        Ok(())
    }
}

// 有效情况：ack在una和nxt中间 => uan < ack <= nxt
// --------+---+---+-----------------------
//         U   A   N
// +-------------------------------+---+---
// N                               U   A
// +---+----------------------------------+
// A   N                                  U
fn ack_is_valid(l: u32, x: u32, r: u32) -> bool {
    (l < x && r >= x) || (l > r && x > l) || (l > r && x <= r) 
}

// 有效情况：seq的起点和终点都在nxt和nxt + wnd中间 => nxt <= seq || (seq + seq.len - 1) < nxt + wnd
fn seq_is_valid(l: u32, x: u32, r: u32) -> bool {
    (l <= x && r > x) || (l > r && x >= l) || (l > r && x < r) 
}